
package br.com.aeternu.controleatendimento.atendimento.ui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ResourceBundle;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.ListSelectionModel;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import org.apache.log4j.Logger;
import br.com.aeternu.controleatendimento.common.ui.EasyJFrame;
import br.com.aeternu.controleatendimento.common.ui.TableCellListener;
import br.com.aeternu.controleatendimento.exception.ControleAtendimentoException;

/**
 * Tela para adição, edição, exclusão e exportação de dados de atendimentos.
 * 
 * @author Janeiro/2014: Junio de Souza Fernandes <DD>
 */
public class UIAtendimento extends EasyJFrame
{

   /** Recursos de texto da classe */
   private static final ResourceBundle BUNDLE = ResourceBundle
            .getBundle("br.com.aeternu.controleatendimento.resources.gui.properties.UIAtendimento");
   /** Registra as operações da classe em arquivo */
   private static Logger logger = Logger.getLogger(UIAtendimento.class);
   /** Número de série (padrão 1L) */
   private static final long serialVersionUID = 1L;
   /** Botão para exclusão de registro */
   private JButton btnExcluirAtendimento;
   /** Botão para exportação de registros */
   private JButton btnExportar;
   /** Botão para inclusão de registro */
   private JButton btnIncluirAtendimento;
   /** Painel que contem os campos visíveis da tela */
   private JPanel contentPane;
   /** Rótulo do período */
   private JLabel lblPeriodo;
   /** Classe que chamou a execução da tela e controla suas ações */
   private IfcUIAtendimento listener;
   /** Período dos registros apresentados */
   private JComboBox<String> periodo;
   /** Painel de rolagem da tabela de dados */
   private JScrollPane scrollPane;
   /** Tabela dos dados apresentados */
   private JTable table;
   /** Ação que sensibiliza a alteração de dados na tabela */
   Action action = new AbstractAction()
   {

      private static final long serialVersionUID = 1L;

      /**
       * (Ver Javadoc da super classe)
       * <P>
       * Acionado quando uma ação é realizada sobre os dados exibidos na tela para atualizar a planilha que contém os dados.
       * 
       * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
       */
      @Override
      public void actionPerformed(ActionEvent e)
      {
         TableCellListener tcl = (TableCellListener) e.getSource();
         logger.info("Row...: " + tcl.getRow());
         logger.info("Column: " + tcl.getColumn());
         logger.info("Old...: " + tcl.getOldValue());
         logger.info("New...: " + tcl.getNewValue());

         if (tcl.getOldValue() != tcl.getNewValue())
            atualizaPlanilha(tcl.getRow(), tcl.getColumn(), tcl.getNewValue());
      }
   };

   /**
    * Cria uma nova instância do tipo <CODE>UIAtendimento</CODE>.
    * <P>
    * 
    * @param listener Classe que chamou a execução da tela e controla suas ações
    * @throws ControleAtendimentoException
    */
   public UIAtendimento(IfcUIAtendimento listener) throws ControleAtendimentoException
   {
      super(BUNDLE.getString(IfcUIAtendimento.BUNDLE_JANELA_TITULO));

      this.listener = listener;

      new TableCellListener(getTable(), action);

      initComponents();
   }

   /**
    * Obtém a instância do botão de exclusão do atendimento.
    * 
    * @return Retorna a instância do botão de exclusão do atendimento.
    */
   public JButton getBtnExcluirAtendimento()
   {
      if (btnExcluirAtendimento == null)
      {
         btnExcluirAtendimento = new JButton(BUNDLE.getString(IfcUIAtendimento.BUNDLE_BOTAO_EXCLUIR_TEXTO));
         btnExcluirAtendimento.setMnemonic(BUNDLE.getString(IfcUIAtendimento.BUNDLE_BOTAO_EXCLUIR_MNEMONICO).charAt(0));
         btnExcluirAtendimento.addActionListener(new ActionListener()
         {

            @Override
            public void actionPerformed(ActionEvent e)
            {
               btnExcluirAtendimentoActionPerformed();
            }
         });
      }

      return btnExcluirAtendimento;
   }

   /**
    * Obtém a instância do botão de exportação dos dados.
    * 
    * @return Retorna a instância do botão de exportação dos dados.
    */
   public JButton getBtnExportar()
   {
      if (btnExportar == null)
      {
         btnExportar = new JButton(BUNDLE.getString(IfcUIAtendimento.BUNDLE_BOTAO_EXPORTAR_TEXTO));
         btnExportar.setMnemonic(BUNDLE.getString(IfcUIAtendimento.BUNDLE_BOTAO_EXPORTAR_MNEMONICO).charAt(0));
         btnExportar.addActionListener(new ActionListener()
         {

            @Override
            public void actionPerformed(ActionEvent e)
            {
               btnExportarActionPerformed();
            }
         });
      }

      return btnExportar;
   }

   /**
    * Obtém a instância do botão de inclusão de novo atendimento.
    * 
    * @return Retorna a instância do botão de inclusão de novo atendimento.
    */
   public JButton getBtnIncluirAtendimento()
   {
      if (btnIncluirAtendimento == null)
      {
         btnIncluirAtendimento = new JButton(BUNDLE.getString(IfcUIAtendimento.BUNDLE_BOTAO_INCLUIR_TEXTO));
         btnIncluirAtendimento.setMnemonic(BUNDLE.getString(IfcUIAtendimento.BUNDLE_BOTAO_INCLUIR_MNEMONICO).charAt(0));
         btnIncluirAtendimento.addActionListener(new ActionListener()
         {

            public void actionPerformed(ActionEvent e)
            {
               btnIncluirAtendimentoActionPerformed();
            }
         });
      }

      return btnIncluirAtendimento;
   }

   /**
    * Obtém a instância do rótulo do período.
    * 
    * @return Retorna a instância do rótulo do período.
    */
   public JLabel getLblPeriodo()
   {
      if (lblPeriodo == null)
      {
         lblPeriodo = new JLabel(BUNDLE.getString(IfcUIAtendimento.BUNDLE_ROTULO_PERIODO_TEXTO));
         lblPeriodo.setDisplayedMnemonic(BUNDLE.getString(IfcUIAtendimento.BUNDLE_ROTULO_PERIODO_MNEMONICO).charAt(0));
         lblPeriodo.setLabelFor(getPeriodo());
      }

      return lblPeriodo;
   }

   /**
    * Obtém a instância do campo que contém o período.
    * 
    * @return Retorna a instância do campo que contém o período.
    */
   public JComboBox<String> getPeriodo()
   {
      if (periodo == null)
      {
         periodo = new JComboBox<String>();
         periodo.setToolTipText(BUNDLE.getString(IfcUIAtendimento.BUNDLE_COMBO_PERIODO_DICA));
         periodo.addItemListener(new ItemListener()
         {

            @Override
            public void itemStateChanged(ItemEvent e)
            {
               periodoItemStateChanged();
            }
         });
      }

      return periodo;
   }

   /**
    * Obtém a instância do painel de rolagem da tabela de dados.
    * 
    * @return Retorna a instância do painel de rolagem da tabela de dados.
    */
   public JScrollPane getScrollPane()
   {
      if (scrollPane == null)
      {
         scrollPane = new JScrollPane();
         scrollPane.setViewportView(getTable());
      }

      return scrollPane;
   }

   /**
    * Obtém a instância da tabela que contém os dados dos atendimentos.
    * 
    * @return Retorna a instância da tabela que contém os dados dos atendimentos.
    */
   public JTable getTable()
   {
      if (table == null)
      {
         table = new JTable();
         table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
         table.setModel(getTableModel());
         table.getColumnModel().getColumn(0).setResizable(false);
         table.getColumnModel().getColumn(0).setPreferredWidth(90);
         table.getColumnModel().getColumn(1).setResizable(false);
         table.getColumnModel().getColumn(1).setPreferredWidth(90);
         table.getColumnModel().getColumn(2).setPreferredWidth(200);
         table.getColumnModel().getColumn(3).setPreferredWidth(200);
         table.getColumnModel().getColumn(4).setResizable(false);
         table.getColumnModel().getColumn(4).setPreferredWidth(130);
         table.getColumnModel().getColumn(5).setResizable(false);
         table.getColumnModel().getColumn(5).setPreferredWidth(130);
         table.getColumnModel().getColumn(6).setPreferredWidth(130);
         table.getColumnModel().getColumn(7).setPreferredWidth(130);
         table.getColumnModel().getColumn(8).setResizable(false);
         table.getColumnModel().getColumn(8).setPreferredWidth(130);
         table.getColumnModel().getColumn(9).setResizable(false);
         table.getColumnModel().getColumn(9).setPreferredWidth(60);
      }
      return table;
   }

   /**
    * (Ver Javadoc da super classe)
    * <P>
    * Fecha a janela.
    * 
    * @see br.com.aeternu.controleatendimento.common.ui.EasyJFrame#sair()
    */
   @Override
   public void sair()
   {
      dispose();
   }

   /**
    * Atualiza a planilha de dados com alguma edição realizada.
    * 
    * @param row Linha editada.
    * @param column Coluna editada.
    * @param newValue Novo valor.
    */
   private void atualizaPlanilha(int row, int column, Object newValue)
   {
      listener.atualizaPlanilha(this, row, column, newValue);
   }

   /**
    * Exclui a linha que contém o atendimento selecionado.
    */
   private void btnExcluirAtendimentoActionPerformed()
   {
      listener.excluirRegistro(this);
   }

   /**
    * Exporta os dados do período selecionado para uma nova planilha, formatada conforme padrão específico.
    */
   private void btnExportarActionPerformed()
   {
      listener.exportarPeriodo(this);
   }

   /**
    * Inclui os dados do atendimento na planilha de dados.
    */
   private void btnIncluirAtendimentoActionPerformed()
   {
      listener.incluirRegistro(this);
   }

   /**
    * Obtém o modelo da tabela de dados.
    * 
    * @return Retorna o modelo da tabela de dados.
    */
   private TableModel getTableModel()
   {
      return new DefaultTableModel(
         new Object[][]{
            {null, null, null, null, null, null, null, null, null, null},
         },
         new String[]{
            BUNDLE.getString(IfcUIAtendimento.BUNDLE_TABELA_COLUNA_DATA),
            BUNDLE.getString(IfcUIAtendimento.BUNDLE_TABELA_COLUNA_TURNO),
            BUNDLE.getString(IfcUIAtendimento.BUNDLE_TABELA_COLUNA_MEDICO),
            BUNDLE.getString(IfcUIAtendimento.BUNDLE_TABELA_COLUNA_PACIENTE),
            BUNDLE.getString(IfcUIAtendimento.BUNDLE_TABELA_COLUNA_TIPOEXAME),
            BUNDLE.getString(IfcUIAtendimento.BUNDLE_TABELA_COLUNA_COORDENACAO),
            BUNDLE.getString(IfcUIAtendimento.BUNDLE_TABELA_COLUNA_EMPRESAPARCEIRA),
            BUNDLE.getString(IfcUIAtendimento.BUNDLE_TABELA_COLUNA_PARTICULAR),
            BUNDLE.getString(IfcUIAtendimento.BUNDLE_TABELA_COLUNA_CONCLUSAOPENDENCIA),
            BUNDLE.getString(IfcUIAtendimento.BUNDLE_TABELA_COLUNA_QUANTIDADE)
         })
      {

         /** Número de série do modelo (padrão 1L) */
         private static final long serialVersionUID = 1L;
         /** Colunas que são editáveis */
         boolean[] columnEditables = new boolean[]{
            true, true, true, true, true, true, true, true, true, true
         };
         /** Classe das colunas */
         Class<?>[] columnTypes = new Class[]{
            String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class,
            String.class, Integer.class
         };

         /**
          * (Ver Javadoc da super classe)
          * 
          * @see javax.swing.table.AbstractTableModel#getColumnClass(int)
          */
         @Override
         public Class<?> getColumnClass(int columnIndex)
         {
            return columnTypes[columnIndex];
         }

         /**
          * (Ver Javadoc da super classe)
          * 
          * @see javax.swing.table.DefaultTableModel#isCellEditable(int, int)
          */
         @Override
         public boolean isCellEditable(int row, int column)
         {
            return columnEditables[column];
         }
      };
   }

   /**
    * Inicializa e configura os componentes da tela no layout específico.
    */
   private void initComponents()
   {
      setBounds(100, 100, 759, 533);
      contentPane = new JPanel();
      contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
      setContentPane(contentPane);
      GroupLayout gl_contentPane = new GroupLayout(contentPane);
      gl_contentPane.setHorizontalGroup(
               gl_contentPane.createParallelGroup(Alignment.LEADING)
                        .addGroup(gl_contentPane.createSequentialGroup()
                                 .addComponent(getBtnIncluirAtendimento())
                                 .addPreferredGap(ComponentPlacement.RELATED)
                                 .addComponent(getBtnExportar())
                                 .addPreferredGap(ComponentPlacement.RELATED, 388, Short.MAX_VALUE)
                                 .addComponent(getBtnExcluirAtendimento()))
                        .addGroup(gl_contentPane.createSequentialGroup()
                                 .addComponent(getLblPeriodo())
                                 .addContainerGap())
                        .addGroup(gl_contentPane.createSequentialGroup()
                                 .addComponent(getPeriodo(), GroupLayout.PREFERRED_SIZE, 190, GroupLayout.PREFERRED_SIZE)
                                 .addContainerGap(551, Short.MAX_VALUE))
                        .addComponent(getScrollPane(), GroupLayout.DEFAULT_SIZE, 741, Short.MAX_VALUE)
               );
      gl_contentPane.setVerticalGroup(
               gl_contentPane.createParallelGroup(Alignment.TRAILING)
                        .addGroup(
                           gl_contentPane
                                    .createSequentialGroup()
                                    .addComponent(getLblPeriodo())
                                    .addPreferredGap(ComponentPlacement.RELATED)
                                    .addComponent(getPeriodo(), GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
                                       GroupLayout.PREFERRED_SIZE)
                                    .addPreferredGap(ComponentPlacement.RELATED)
                                    .addComponent(getScrollPane(), GroupLayout.DEFAULT_SIZE, 407, Short.MAX_VALUE)
                                    .addGap(18)
                                    .addGroup(gl_contentPane.createParallelGroup(Alignment.BASELINE)
                                             .addComponent(getBtnIncluirAtendimento())
                                             .addComponent(getBtnExcluirAtendimento())
                                             .addComponent(getBtnExportar())))
               );
      contentPane.setLayout(gl_contentPane);
      setVisible(true);
   }

   /**
    * Recarrega os atendimentos conforme o período especificado.
    */
   private void periodoItemStateChanged()
   {
      listener.trocaPeriodo(this);
   }
}
